home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / devel / vbcc-src / ic.c < prev    next >
C/C++ Source or Header  |  1999-01-01  |  56KB  |  1,605 lines

  1. /*  $VER: vbcc (ic.c) V0.4  */
  2.  
  3. #include "vbc.h"
  4.  
  5. static char FILE_[]=__FILE__;
  6.  
  7. static struct IC *first_pushed;
  8.  
  9. int do_arith(np,struct IC *,np,struct obj *);
  10.  
  11. void gen_test(struct obj *o,int t,int branch,int label)
  12. /*  Generiert ein test o, branch label und passt auf, dass      */
  13. /*  kein TEST const generiert wird.                             */
  14. {
  15.     struct IC *new;
  16.     if(o->flags&KONST){
  17.         eval_const(&o->val,t);
  18.         if(zdeqto(vdouble,d2zd(0.0))&&zleqto(vlong,l2zl(0L))&&zuleqto(vulong,ul2zul(0UL))){
  19.             if(branch==BEQ) branch=BRA; else branch=0;
  20.         }else{
  21.             if(branch==BNE) branch=BRA; else branch=0;
  22.         }
  23.     }else{
  24.         new=mymalloc(ICS);
  25.         new->code=TEST;
  26.         new->q2.flags=new->z.flags=0;
  27.         new->typf=t;
  28.         new->q1=*o;
  29.         add_IC(new);
  30.     }
  31.     if(branch){
  32.         new=mymalloc(ICS);
  33.         new->code=branch;
  34.         new->typf=label;
  35.         add_IC(new);
  36.     }
  37. }
  38.  
  39. void inline_memcpy(np z,np q,zlong size)
  40. /*  fuegt ein ASSIGN-IC ein, das memcpy(z,q,size) entspricht    */
  41. {
  42.     struct IC *new=mymalloc(ICS);
  43.     if((z->ntyp->flags&NQ)!=POINTER) ierror(0);
  44.     if((q->ntyp->flags&NQ)!=POINTER) ierror(0);
  45.  
  46.     gen_IC(z,0,0);
  47.     if(z->o.flags&DREFOBJ){
  48.         struct IC *n2=mymalloc(ICS);
  49.         n2->code=ASSIGN;
  50.         n2->typf=q->ntyp->flags;
  51.         n2->q1=z->o;
  52.         get_scratch(&n2->z,z->ntyp->flags,z->ntyp->next->flags,z->ntyp);
  53.         n2->q2.flags=0;
  54.         n2->q2.val.vlong=sizetab[POINTER];
  55.         new->z=n2->z;
  56.         add_IC(n2);
  57.     }else{
  58.         new->z=z->o;
  59.     }
  60.     if(new->z.flags&VARADR) new->z.flags&=~VARADR; else new->z.flags|=DREFOBJ;
  61.  
  62.     gen_IC(q,0,0);
  63.     if(q->o.flags&DREFOBJ){
  64.         struct IC *n2=mymalloc(ICS);
  65.         n2->code=ASSIGN;
  66.         n2->typf=q->ntyp->flags;
  67.         n2->q1=q->o;
  68.         get_scratch(&n2->z,q->ntyp->flags,q->ntyp->next->flags,q->ntyp);
  69.         n2->q2.flags=0;
  70.         n2->q2.val.vlong=sizetab[POINTER];
  71.         new->q1=n2->z;
  72.         add_IC(n2);
  73.     }else{
  74.         new->q1=q->o;
  75.     }
  76.     if(new->q1.flags&VARADR) new->q1.flags&=~VARADR; else new->q1.flags|=DREFOBJ;
  77.  
  78.     new->code=ASSIGN;
  79.     new->typf=UNSIGNED|CHAR;
  80.     new->q2.flags=0;
  81.     new->q2.val.vlong=size;
  82.     add_IC(new);
  83. }
  84.  
  85. void add_IC(struct IC *new)
  86. /*  fuegt ein IC ein                                            */
  87. {
  88.     int code;
  89.     if(!new) return;
  90.     if(nocode) {free(new);return;}
  91.     new->next=0;
  92.     new->q1.am=new->q2.am=new->z.am=0;
  93.     new->line=line; new->file=0;
  94.     code=new->code;
  95.     if(code>=BEQ&&code<=BRA) new->q1.flags=new->q2.flags=new->z.flags=0;
  96.     if(code==ALLOCREG||code==FREEREG||code==SAVEREGS||code==RESTOREREGS) new->typf=0;
  97.     if(DEBUG&64){ pric(stdout,first_ic);printf("new\n");pric2(stdout,new);printf("-\n");}
  98.     if(new->q1.flags&VAR){
  99.         if(!new->q1.v) ierror(0);
  100.         new->q1.v->flags|=USEDASSOURCE;
  101.         if(code==ADDRESS||(new->q1.flags&VARADR)) new->q1.v->flags|=USEDASADR;
  102.         new->q1.v->priority+=currentpri;
  103.     }
  104.     if(new->q2.flags&VAR){
  105.         if(!new->q2.v) ierror(0);
  106.         new->q2.v->flags|=USEDASSOURCE;
  107.         if(code==ADDRESS||(new->q2.flags&VARADR)) new->q2.v->flags|=USEDASADR;
  108.         new->q2.v->priority+=currentpri;
  109.     }
  110.     if(new->z.flags&VAR){
  111.         if(!new->z.v) ierror(0);
  112.         if(new->z.flags&DREFOBJ) new->z.v->flags|=USEDASSOURCE; else new->z.v->flags|=USEDASDEST;
  113.         new->z.v->priority+=currentpri;
  114.     }
  115.     if(/*(c_flags_val[0].l&2)&&*/code==LABEL){
  116.     /*  entfernt Spruenge zu direkt folgenden Labels    */
  117.         struct IC *p=last_ic;
  118.         while(p){
  119.             if(p->typf==new->typf&&p->code>=BEQ&&p->code<=BRA){
  120.                 struct IC *n;
  121.                 if(DEBUG&1) printf("%s l%d deleted\n",ename[p->code],p->typf);
  122.                 n=p->next;
  123.                 remove_IC(p);
  124.                 p=n;
  125.             }else{
  126.                 if(p->code!=LABEL) break;
  127.                 p=p->prev;
  128.             }
  129.         }
  130.     }
  131.     if(last_ic){
  132.         if(code==ASSIGN){
  133.             if((last_ic->z.flags&(REG|SCRATCH|DREFOBJ))==(REG|SCRATCH)&&(new->q1.flags==last_ic->z.flags)&&last_ic->z.reg==new->q1.reg/*&&last_ic->code!=CALL*/){
  134.                 if(USEQ2ASZ||!(last_ic->q2.flags®)||!(new->z.flags®)||last_ic->q2.reg!=new->z.reg){
  135.                     if(USEQ2ASZ||!(last_ic->q2.flags&VAR)||!(new->z.flags&VAR)||last_ic->q2.v!=new->z.v){
  136.                     /*  verbindet op a,b->reg,move reg->c zu op a,b->c  */
  137.                     /*  hier fehlt aber noch Registerfreigabe           */
  138.                         last_ic->z=new->z;
  139.                         if(DEBUG&1) printf("move and op combined\n");
  140.                         if((new->q1.flags&SCRATCH)&&(new->q1.reg!=new->z.reg||!(new->z.flags®)))
  141.                             free_reg(new->q1.reg);
  142.                         free(new);
  143.                         return;
  144.                     }
  145.                 }
  146.             }
  147.             if((last_ic->z.flags&(VAR|SCRATCH|DREFOBJ))==(VAR|SCRATCH)&&(new->q1.flags==last_ic->z.flags)&&last_ic->z.v==new->q1.v/*&&last_ic->code!=CALL*/){
  148.                 if(USEQ2ASZ||!(last_ic->q2.flags®)||!(new->z.flags®)||last_ic->q2.reg!=new->z.reg){
  149.                     if(USEQ2ASZ||!(last_ic->q2.flags&VAR)||!(new->z.flags&VAR)||last_ic->q2.v!=new->z.v){
  150.                     /*  verbindet op a,b->scratch,move scratch->c zu op a,b->c  */
  151.                     /*  hier fehlt aber noch Registerfreigabe           */
  152.                         last_ic->z=new->z;
  153.                         if(DEBUG&1) printf("move and op combined(2)\n");
  154. /*                        if((new->q1.flags&SCRATCH)&&(new->q1.reg!=new->z.reg||!(new->z.flags®)))
  155.                             free_reg(new->q1.reg);*/
  156.                         free(new);
  157.                         return;
  158.                     }
  159.                 }
  160.             }
  161.  
  162.         }
  163.         if(last_ic->code==BRA){
  164.             if(code!=LABEL&&code!=ALLOCREG&&code!=FREEREG){
  165.             /*  loescht alles nach bra bis ein Label kommt  */
  166.             /*  momentan noch nicht perfekt, da es bei alloc/freereg stoppt */
  167.                 free(new);
  168.                 if(DEBUG&1) printf("Unreachable Statement deleted\n");
  169.                 return;
  170.             }
  171.             if(last_ic->prev&&code==LABEL){
  172.             /*  ersetzt bcc l1;bra l2;l1 durch b!cc l2      */
  173.                 if(last_ic->prev->code>=BEQ&&last_ic->prev->code<=BGT&&new->typf==last_ic->prev->typf){
  174.                     if(DEBUG&1) printf("%s l%d;%s l%d; substituted\n",ename[last_ic->prev->code],last_ic->prev->typf,ename[last_ic->code],last_ic->typf);
  175.                     if(last_ic->prev->code&1) last_ic->prev->code--;
  176.                                     else      last_ic->prev->code++;
  177.                     last_ic->prev->typf=last_ic->typf;
  178.                     last_ic=last_ic->prev;
  179.                     free(last_ic->next);
  180.                     last_ic->next=new;new->prev=last_ic;
  181.                     last_ic=new;
  182.                     return;
  183.                 }
  184.             }
  185.         }
  186. /*        }*/
  187.         new->prev=last_ic;
  188.         last_ic->next=new;
  189.         last_ic=new;
  190.     }else{
  191.         last_ic=new;first_ic=new;new->prev=0;
  192.     }
  193.     ic_count++;
  194.     /*  Merken, on Fliesskomma benutzt wurde    */
  195.     if(code!=LABEL&&(code<BEQ||code>BRA)){
  196.         if((new->typf&NQ)==FLOAT||(new->typf&NQ)==DOUBLE) float_used=1;
  197.         if(code==CONVFLOAT||code==CONVDOUBLE) float_used=1;
  198.     }
  199.     if((new->q1.flags&SCRATCH)&&(new->q1.reg!=new->z.reg||!(new->z.flags®)))
  200.         free_reg(new->q1.reg);
  201.     if((new->q2.flags&SCRATCH)&&(new->q2.reg!=new->z.reg||!(new->z.flags®)))
  202.         free_reg(new->q2.reg);
  203. }
  204. void gen_IC(np p,int ltrue,int lfalse)
  205. /*  Erzeugt eine IC-Liste aus einer expression      */
  206. {
  207.     struct IC *new; struct regargs_list *rl;
  208.     if(!p) return;
  209.     if(p->flags==STRING){
  210.     /*  hier fehlt noch die Verwaltung der String-Inhalte   */
  211.         p->o.v=add_var(empty,clone_typ(p->ntyp),STATIC,p->cl);
  212.         p->o.v->flags|=DEFINED;
  213.         p->o.flags=VAR;
  214.         p->o.reg=0;
  215.         p->o.val=p->val;
  216.         return;
  217.     }
  218.     if(p->flags==IDENTIFIER){
  219. /*        p->o.v=find_var(p->identifier,0);*/
  220.         p->o.flags=VAR;
  221.         p->o.reg=0;
  222.         p->o.val=p->val;
  223.         return;
  224.     }
  225.     if(p->flags==CEXPR||p->flags==PCEXPR){
  226.         if(p->left){
  227.             if(p->left->flags==POSTINC) p->left->flags=PREINC;
  228.             if(p->left->flags==POSTDEC) p->left->flags=PREDEC;
  229.             gen_IC(p->left,0,0);
  230.             if(p->left->o.flags&SCRATCH) free_reg(p->left->o.reg);
  231.         }
  232.         if(p->right){
  233.             if(p->right->flags==POSTINC) p->right->flags=PREINC;
  234.             if(p->right->flags==POSTDEC) p->right->flags=PREDEC;
  235.             gen_IC(p->right,0,0);
  236.             if(p->right->o.flags&SCRATCH) free_reg(p->right->o.reg);
  237.         }
  238.         p->o.flags=KONST;
  239.         p->o.val=p->val;
  240.         p->o.reg=0;
  241.         return;
  242.     }
  243.     if(p->flags==KOMMA){
  244.         if(p->left->sidefx){
  245.             gen_IC(p->left,0,0);
  246.             if(p->left->o.flags&SCRATCH) free_reg(p->left->o.reg);
  247.         } else error(129);
  248.         gen_IC(p->right,0,0);
  249.         p->o=p->right->o;
  250.         return;
  251.     }
  252.     if(p->flags==CAST){
  253.         gen_IC(p->left,0,0);
  254.         if((p->ntyp->flags&NQ)==VOID){
  255.             if(p->left->o.flags&SCRATCH) free_reg(p->left->o.reg);
  256.             p->o.flags=0;
  257.         }else{
  258.             convert(p->left,p->ntyp->flags&NU);
  259.             p->o=p->left->o;
  260.         }
  261.         return;
  262.     }
  263.     if(p->flags==FIRSTELEMENT){
  264.         gen_IC(p->left,0,0);
  265.         p->o=p->left->o;
  266.         return;
  267.     }
  268.     new=mymalloc(ICS);
  269.     new->typf=p->ntyp->flags&NU;
  270.     new->q1.reg=new->q2.reg=new->z.reg=0;
  271.     new->q1.flags=new->q2.flags=new->z.flags=0;
  272.     if((p->flags>=LSHIFT&&p->flags<=MOD)||(p->flags>=OR&&p->flags<=AND)||p->flags==PMULT){
  273.         do_arith(p,new,0,0);
  274.         return;
  275.     }
  276.     if(p->flags==CONTENT){
  277.         gen_IC(p->left,0,0);
  278.         if(p->left->o.flags&VARADR){
  279.             free(new);
  280.             p->o=p->left->o;
  281.             p->o.flags&=~VARADR;
  282.             return;
  283.         }
  284.         if(!(p->left->o.flags&DREFOBJ)){
  285.             free(new);
  286.             p->o=p->left->o;
  287.             p->o.flags|=DREFOBJ;
  288.         }else{
  289.           if(p->left->o.flags&SCRATCH){
  290.             new->z=p->left->o;
  291.             new->z.flags&=~DREFOBJ;
  292.           }else{
  293.             get_scratch(&new->z,p->left->ntyp->flags,p->ntyp->flags,p->left->ntyp);
  294.           }
  295.           new->code=ASSIGN;new->typf=POINTER;
  296.           new->q1=p->left->o;
  297.           new->q2.val.vlong=sizetab[POINTER];
  298.           p->o=new->z;
  299.           add_IC(new);
  300.           p->o.flags|=DREFOBJ;
  301.         }
  302.         return;
  303.     }
  304.     if(p->flags==ASSIGN){
  305.         new->code=ASSIGN;
  306.         gen_IC(p->right,0,0);
  307.         gen_IC(p->left,0,0);
  308.         convert(p->right,p->ntyp->flags&NU);
  309.         new->q1=p->right->o;
  310.         new->z=p->left->o;
  311.         new->q2.val.vlong=szof(p->left->ntyp);
  312.         p->o=new->z;
  313.         add_IC(new);
  314.         return;
  315.     }
  316.     if(p->flags==ASSIGNADD){
  317.     /*  das hier ist nicht besonders schoen */
  318.         struct obj o;struct IC *n;int f;
  319.         if(p->right->right==0){
  320.         /*  sowas wie a+=0 wurde wegoptimiert   */
  321.             free(new);
  322.             p->o=p->left->o;
  323.             return;
  324.         }
  325.         f=do_arith(p->right,new,p->left,&o);
  326.         if(!f) {ierror(0);return;}
  327.         if(f>1) {ierror(0);return;}
  328.         if(!nocode&&(o.flags&(SCRATCH|REG))==(SCRATCH|REG)&&!regs[o.reg]){
  329.         /*  ueberfluessiges FREEREG entfernen   */
  330.             n=last_ic;
  331.             while(n){
  332.                 if(n->code==FREEREG&&n->q1.reg==o.reg){
  333.                     remove_IC(n);if(!nocode) regs[o.reg]=1;
  334.                     break;
  335.                 }
  336.                 n=n->prev;
  337.             }
  338.         }
  339.         convert(p->right,p->ntyp->flags&NU);
  340.         new=mymalloc(ICS);
  341.         new->typf=p->ntyp->flags&NU;
  342.         new->q2.flags=0;
  343.         new->code=ASSIGN;
  344.         new->q1=p->right->o;
  345.         new->z=o;
  346.         new->q2.val.vlong=szof(p->left->ntyp);
  347.         p->o=new->z;
  348.         add_IC(new);
  349.         return;
  350.     }
  351.     if(p->flags==MINUS||p->flags==KOMPLEMENT){
  352.         new->code=p->flags;
  353.         gen_IC(p->left,0,0);
  354.         convert(p->left,p->ntyp->flags);
  355.         if(regok(p->left->o.reg,p->ntyp->flags,0)&&(p->left->o.flags&SCRATCH)){
  356.             new->z=p->left->o;
  357.             new->z.flags&=~DREFOBJ;
  358.         }else{
  359.             get_scratch(&new->z,p->left->ntyp->flags,0,p->left->ntyp);
  360.         }
  361.         new->q1=p->left->o;
  362.         p->o=new->z;
  363.         add_IC(new);
  364.         return;
  365.     }
  366.     if(p->flags==ADDRESS||p->flags==ADDRESSA||p->flags==ADDRESSS){
  367.         new->code=ADDRESS;
  368.         new->typf=p->left->ntyp->flags&NU;
  369.         gen_IC(p->left,0,0);
  370.         if(p->left->o.flags&VAR) p->left->o.v->flags|=USEDASSOURCE|USEDASDEST;
  371.         if(p->left->o.flags&DREFOBJ){
  372.             free(new);
  373.             p->o=p->left->o;
  374.             p->o.flags&=~DREFOBJ;
  375.             return;
  376.         }
  377.         if((p->left->o.flags&VAR)&&!(p->left->o.flags&VARADR)
  378.            &&(p->left->o.v->storage_class==EXTERN||p->left->o.v->storage_class==STATIC)){
  379.             free(new);
  380.             p->o=p->left->o;
  381.             p->o.flags|=VARADR;
  382.             return;
  383.         }
  384.         new->q1=p->left->o;
  385.         get_scratch(&new->z,POINTER,p->ntyp->next->flags,0);
  386.         p->o=new->z;
  387.         add_IC(new);
  388.         return;
  389.     }
  390.     if(p->flags==LAND||p->flags==LOR){
  391.         int l1,l2,l3,l4;
  392. /*        printf("%s true=%d false=%d\n",ename[p->flags],ltrue,lfalse);*/
  393.         l1=++label;if(!ltrue) {l2=++label;l3=++label;l4=++label;}
  394.         if(!ltrue){if(p->flags==LAND) gen_IC(p->left,l1,l3);
  395.                     else gen_IC(p->left,l3,l1);
  396.         }else     {if(p->flags==LAND) gen_IC(p->left,l1,lfalse);
  397.                     else gen_IC(p->left,ltrue,l1);
  398.         }
  399.         if(p->left->o.flags!=0){
  400.             if(p->flags==LAND)
  401.                 gen_test(&p->left->o,p->left->ntyp->flags,BEQ,((!ltrue)?l3:lfalse));
  402.             else
  403.                 gen_test(&p->left->o,p->left->ntyp->flags,BNE,((!ltrue)?l3:ltrue));
  404.         }
  405.         gen_label(l1);
  406.         if(!ltrue){if(p->flags==LAND) gen_IC(p->right,l2,l3);
  407.                     else gen_IC(p->right,l3,l2);
  408.         }else      gen_IC(p->right,ltrue,lfalse);
  409.         if(p->right->o.flags!=0){
  410.             if(p->flags==LAND)
  411.                 gen_test(&p->right->o,p->right->ntyp->flags,BEQ,((!ltrue)?l3:lfalse));
  412.             else
  413.                 gen_test(&p->right->o,p->right->ntyp->flags,BNE,((!ltrue)?l3:ltrue));
  414.         }
  415.         if(!ltrue){
  416.             gen_label(l2);
  417.             if(p->flags==LAND) gen_cond(&p->o,0,l3,l4); else gen_cond(&p->o,1,l3,l4);
  418.         }else{
  419.             new=mymalloc(ICS);
  420.             new->code=BRA;
  421.             if(p->flags==LAND) new->typf=ltrue; else new->typf=lfalse;
  422.             add_IC(new);
  423.         }
  424.         if(ltrue) p->o.flags=0;
  425.         return;
  426.     }
  427.     if(p->flags==NEGATION){
  428.         int l1,l2,l3;
  429.         if(!ltrue) {l1=++label;l2=++label;l3=++label;}
  430.         if(ltrue) gen_IC(p->left,lfalse,ltrue); else gen_IC(p->left,l1,l3);
  431.         if(!p->left->o.flags) {free(new);p->o.flags=0;
  432.         }else{
  433.             gen_test(&p->left->o,p->left->ntyp->flags,BNE,((!ltrue)?l1:lfalse));
  434.         }
  435.         if(ltrue){
  436.             new=mymalloc(ICS);
  437.             new->code=BRA;
  438.             if(!ltrue) new->typf=l2; else new->typf=ltrue;
  439.             add_IC(new);
  440.             p->o.flags=0;
  441.         }else{
  442.             gen_label(l3);
  443.             gen_cond(&p->o,0,l1,l2);
  444.         }
  445.         return;
  446.     }
  447.     if(p->flags>=EQUAL&&p->flags<=GREATEREQ){
  448.         int l1,l2,l3,tl,tr;
  449.         if(!ltrue) {l1=++label;l2=++label;l3=++label;}
  450.         if(p->left->flags==CEXPR){
  451.         /*  Konstanten nach rechts  */
  452.             np merk;merk=p->left;p->left=p->right;p->right=merk;
  453.             if(p->flags==LESS) p->flags=GREATER;
  454.             else if(p->flags==LESSEQ) p->flags=GREATEREQ;
  455.             else if(p->flags==GREATER) p->flags=LESS;
  456.             else if(p->flags==GREATEREQ) p->flags=LESSEQ;
  457.         }
  458.         new->code=COMPARE;
  459.         tl=p->left->ntyp->flags&NU;tr=p->right->ntyp->flags&NU;
  460.         if(p->right->flags==CEXPR&&(tr&NQ)<FLOAT&&(tl&NQ)<FLOAT){
  461.             int negativ;
  462.             eval_constn(p->right);
  463.             if(zlleq(vlong,0)) negativ=1; else negativ=0;
  464.             if((tl&UNSIGNED)||(tr&UNSIGNED)) negativ=0;
  465.             if((!negativ||zlleq(t_min[tl],vlong))&&(negativ||zulleq(vulong,t_max[tl]))){
  466.                 convert(p->right,tl);
  467.                 tr=tl;
  468.             }
  469.         }
  470.         if(arith(tl&NQ)&&(tl!=tr||!shortcut(COMPARE,tl))){
  471.             struct Typ *t;
  472.             t=arith_typ(p->left->ntyp,p->right->ntyp);
  473.             new->typf=t->flags&NU;
  474.             freetyp(t);
  475.         }else{
  476.             new->typf=p->left->ntyp->flags&NU;
  477.         }
  478.         gen_IC(p->left,0,0);
  479.         convert(p->left,new->typf);
  480.         gen_IC(p->right,0,0);
  481.         convert(p->right,new->typf);
  482.         new->q1=p->left->o;
  483.         new->q2=p->right->o;
  484.         new->z.flags=0;
  485.         add_IC(new);
  486.         new=mymalloc(ICS);
  487.         if(p->flags==EQUAL) new->code=BEQ;
  488.         if(p->flags==INEQUAL) new->code=BNE;
  489.         if(p->flags==LESS) new->code=BLT;
  490.         if(p->flags==LESSEQ) new->code=BLE;
  491.         if(p->flags==GREATER) new->code=BGT;
  492.         if(p->flags==GREATEREQ) new->code=BGE;
  493.         if(ltrue) new->typf=ltrue; else new->typf=l1;
  494.         add_IC(new);
  495.         if(ltrue){
  496.             new=mymalloc(ICS);
  497.             new->code=BRA;
  498.             new->typf=lfalse;
  499.             add_IC(new);
  500.             p->o.flags=0;
  501.         }else{
  502.             gen_label(l3);
  503.             gen_cond(&p->o,1,l1,l2);
  504.         }
  505.         return;
  506.     }
  507.     if(p->flags==CALL){
  508.         int r=0;struct obj *op,ret_obj;zlong sz;
  509.         int mregs[MAXR+1];
  510. #ifdef ORDERED_PUSH
  511.         struct IC *merk_fp,*lp;
  512. #endif
  513.         if(p->left->flags==ADDRESS&&p->left->left->flags==IDENTIFIER){
  514.             struct Var *v;
  515.             gen_IC(p->left,0,0); r=1;
  516.             v=p->left->o.v;
  517.             if(v->fi&&v->fi->first_ic&&(c_flags_val[0].l&4096)){
  518.             /*  function call inlining  */
  519.                 struct argument_list *al;
  520.                 struct Var *vp,**argl1,**argl2;
  521.                 struct IC *ip;int lc;
  522.                 int arg_cnt=0,i;
  523.                 if(DEBUG&1024){
  524.                     printf("inlining call to <%s>\n",v->identifier);
  525.                     for(vp=v->fi->vars;vp;vp=vp->next)
  526.                         printf("%s(%ld)\n",vp->identifier,zl2l(vp->offset));
  527.                 }
  528.                 for(vp=v->fi->vars;vp;vp=vp->next){
  529.                     if((zleqto(vp->offset,l2zl(0L))||vp->reg)&&*vp->identifier&&(vp->storage_class==AUTO||vp->storage_class==REGISTER)) arg_cnt++;
  530.                 }
  531.  
  532.                 /*  Argumente in die ersten Parametervariablen kopieren */
  533.                 argl1=mymalloc(arg_cnt*sizeof(struct Var *));
  534.                 argl2=mymalloc(arg_cnt*sizeof(struct Var *));
  535.  
  536.                 al=p->alist;vp=v->fi->vars;i=0;
  537.                 while(al){
  538.                     while(vp&&(!*vp->identifier||(!zleqto(vp->offset,l2zl(0L))&&!vp->reg)||(vp->storage_class!=REGISTER&&vp->storage_class!=AUTO))) vp=vp->next;
  539.                     if(!vp){ error(39); break; }
  540.                     if(i>=arg_cnt) ierror(0);
  541.                     if(DEBUG&1024) printf("arg: %s(%ld)\n",vp->identifier,zl2l(vp->offset));
  542.                     argl1[i]=vp;
  543.                     argl2[i]=add_var(empty,clone_typ(vp->vtyp),vp->storage_class,0);
  544.                     if(!al->arg) ierror(0);
  545.                     gen_IC(al->arg,0,0);
  546.                     convert(al->arg,vp->vtyp->flags);
  547.                     new=mymalloc(ICS);
  548.                     new->code=ASSIGN;
  549.                     new->q1=al->arg->o;
  550.                     new->q2.flags=0;
  551.                     new->q2.val.vlong=szof(vp->vtyp);
  552.                     new->z.flags=VAR;
  553.                     new->z.val.vlong=l2zl(0L);
  554.                     new->z.v=argl2[i];
  555.                     new->typf=vp->vtyp->flags;
  556.                     add_IC(new);
  557.                     i++;
  558.                     al=al->next;
  559.                     vp=vp->next;
  560.                 }
  561.                 if(i<arg_cnt){ error(83); arg_cnt=i;}
  562.  
  563.                 /*  Kopien der Variablen erzeugen   */
  564.                 for(vp=v->fi->vars;vp;vp=vp->next){
  565.                     vp->inline_copy=0;
  566.                 }
  567.                 for(i=0;i<arg_cnt;i++){
  568.                     if(argl1[i]){
  569.                         if(!argl2[i]) ierror(0);
  570.                         argl1[i]->inline_copy=argl2[i];
  571.                     }
  572.                 }
  573.  
  574.                 /*  Rueckgabewert   */
  575.                 if((p->ntyp->flags&NQ)!=VOID){
  576.                     p->o.flags=SCRATCH|VAR;
  577.                     p->o.reg=0;p->o.val.vlong=l2zl(0L);
  578.                     p->o.v=add_var(empty,clone_typ(p->ntyp),AUTO,0);
  579.                 }else{
  580.                     p->o.flags=0;
  581.                 }
  582.  
  583.                 free(argl1);
  584.                 free(argl2);
  585.  
  586.                 /*  Code einfuegen und Labels umschreiben   */
  587.                 ip=v->fi->first_ic;lc=0;
  588.                 while(ip){
  589.                     struct Var *iv;
  590.                     int c;
  591.                     new=mymalloc(ICS);
  592.                     memcpy(new,ip,ICS);
  593.                     c=ip->code;
  594.                     /*  evtl. ist ein IC praktisch ein SETRETURN, falls das */
  595.                     /*  Rueckgabeziel ueber Parameterzeiger angespr. wird   */
  596.                     if(ip->z.flags&VAR){
  597.                       iv=ip->z.v;
  598.                       if(iv->storage_class==AUTO||iv->storage_class==REGISTER){
  599.                         if(!*iv->identifier&&zleqto(iv->offset,l2zl(0L))){
  600.                           new->z=p->o;
  601.                         }else{
  602.                           if(!iv->inline_copy){
  603.                             iv->inline_copy=add_var(empty,clone_typ(iv->vtyp),iv->storage_class,0);
  604.                             iv->inline_copy->reg=iv->reg;
  605.                           }
  606.                           new->z.v=iv->inline_copy;
  607.                         }/*else if(iv->inline_copy) ierror(0);*/
  608.                       }
  609.                     }
  610.                     /*  Kopien aller auto/register Variablen erzeugen   */
  611.                     if(ip->q1.flags&VAR){
  612.                       iv=ip->q1.v;
  613.                       if(iv->storage_class==AUTO||iv->storage_class==REGISTER){
  614.                         if(!iv->inline_copy){
  615.                           iv->inline_copy=add_var(empty,clone_typ(iv->vtyp),iv->storage_class,0);
  616.                           iv->inline_copy->reg=iv->reg;
  617.                         }
  618.                         new->q1.v=iv->inline_copy;
  619.                       }/*else if(iv->inline_copy) ierror(0);*/
  620.                     }
  621.                     if(ip->q2.flags&VAR){
  622.                       iv=ip->q2.v;
  623.                       if(iv->storage_class==AUTO||iv->storage_class==REGISTER){
  624.                         if(!iv->inline_copy){
  625.                           iv->inline_copy=add_var(empty,clone_typ(iv->vtyp),iv->storage_class,0);
  626.                           iv->inline_copy->reg=iv->reg;
  627.                         }
  628.                         new->q2.v=iv->inline_copy;
  629.                       }/*else if(iv->inline_copy) ierror(0);*/
  630.                     }
  631.                     if(c==CALL) function_calls+=currentpri;
  632.                     if(c==LABEL||(c>=BEQ&&c<=BRA)){
  633.                         if(new->typf>lc) lc=new->typf;
  634.                         new->typf+=label;
  635.                     }
  636.                     if(c==SETRETURN){
  637.                         new->code=ASSIGN;
  638.                         new->z=p->o;
  639.                     }
  640.                     add_IC(new);
  641.                     ip=ip->next;
  642.                 }
  643.                 label+=lc;
  644.                 return;
  645.             }
  646.             /*  einige spezielle Inline-Funktionen; das setzt voraus, dass  */
  647.             /*  diese in den Headerfiles passend deklariert werden          */
  648.             if(v->storage_class==EXTERN){
  649.                 if(!strcmp(v->identifier,"strlen")&&p->alist&&p->alist->arg){
  650.                     np n=p->alist->arg;
  651.                     if(n->flags==ADDRESSA&&n->left->flags==STRING){
  652.                         struct const_list *cl;zulong len=ul2zul(0UL);
  653.                         cl=n->left->cl;
  654.                         while(cl){
  655.                             if(zleqto(l2zl(0L),zc2zl(cl->other->val.vchar))) break;
  656.                             len=zuladd(len,ul2zul(1UL));
  657.                             cl=cl->next;
  658.                         }
  659.                         p->o.val.vulong=len;
  660.                         eval_const(&p->o.val,UNSIGNED|LONG);
  661.                         insert_const(p);
  662.                         insert_const2(&p->o.val,p->ntyp->flags);
  663.                         p->flags=CEXPR;
  664.                         p->o.flags=KONST;
  665.                         return;
  666.                     }
  667.                 }
  668.  
  669.                 if(INLINEMEMCPY>0&&(optflags&2)){
  670.                     if(!strcmp(v->identifier,"strcpy")&&p->alist&&p->alist->next&&p->alist->next->arg){
  671.                         np n=p->alist->next->arg;
  672.                         if(n->flags==ADDRESSA&&n->left->flags==STRING){
  673.                             struct const_list *cl;zlong len=l2zl(0L);
  674.                             cl=n->left->cl;
  675.                             while(cl){
  676.                                 len=zladd(len,l2zl(1L));
  677.                                 if(zleqto(zc2zl(cl->other->val.vchar),l2zl(0L))) break;
  678.                                 cl=cl->next;
  679.                             }
  680.                             if(zlleq(len,l2zl((long)INLINEMEMCPY))){
  681.                                 inline_memcpy(p->alist->arg,n,len);
  682.                                 p->o=p->alist->arg->o;
  683.                                 return;
  684.                             }
  685.                         }
  686.                     }
  687.                     if(!strcmp(v->identifier,"memcpy")){
  688.                         if(p->alist&&p->alist->next&&p->alist->next->next
  689.                            &&p->alist->next->next->arg
  690.                            &&p->alist->next->next->arg->flags==CEXPR){
  691.                             eval_constn(p->alist->next->next->arg);
  692.                             if(zlleq(vlong,l2zl((long)INLINEMEMCPY))){
  693.                                 inline_memcpy(p->alist->arg,p->alist->next->arg,vlong);
  694.                                 p->o=p->alist->arg->o;
  695.                                 return;
  696.                             }
  697.                         }
  698.                     }
  699.                 }
  700.             }
  701.         }
  702.         rl=0;
  703.         if(!(optflags&2)){
  704.           int r;
  705.           for(r=1;r<=MAXR;r++){mregs[r]=regs[r];regs[r]&=~32;}
  706.         }
  707. #ifdef ORDERED_PUSH
  708.         merk_fp=first_pushed;
  709.         first_pushed=0;
  710.         lp=last_ic;
  711. #endif
  712. #ifdef HAVE_REGPARMS
  713.         if(!freturn(p->ntyp)){
  714.           struct IC *new2;
  715.           new2=mymalloc(ICS);
  716.           new2->code=ADDRESS;
  717.           new2->typf=p->ntyp->flags&NU;
  718.           new2->q1.flags=VAR;
  719.           new2->q1.v=add_var(empty,clone_typ(p->ntyp),AUTO,0);
  720.           new2->q1.val.vlong=l2zl(0L);
  721.           op=&new2->q1;
  722.           new2->q2.flags=0;
  723.           get_scratch(&new2->z,POINTER,p->ntyp->flags&NU,0);
  724.           ret_obj=new2->z;
  725.           add_IC(new2);
  726.         }
  727.         {
  728.             struct reg_handle reg_handle=empty_reg_handle;
  729.             if(!freturn(p->ntyp)){
  730.               static struct Typ ptyp={POINTER};
  731.               int reg;
  732.               ptyp.next=p->ntyp;
  733.               reg=reg_parm(®_handle,&ptyp,0);
  734.               if(!reg) ierror(0);
  735.               sz=push_args(p->alist,p->left->ntyp->next->exact,0,&rl,®_handle,&ret_obj,reg);
  736.             }else{
  737.               sz=push_args(p->alist,p->left->ntyp->next->exact,0,&rl,®_handle,0,-1);
  738.             }
  739.         }
  740. #else
  741.         sz=push_args(p->alist,p->left->ntyp->next->exact,0,&rl);
  742. #endif
  743.         if(!r) gen_IC(p->left,0,0);
  744.         if(!(p->left->o.flags&DREFOBJ)){
  745.             free(new);
  746.             p->o=p->left->o;
  747.             if(p->o.flags&VARADR) p->o.flags&=~VARADR;
  748.              else p->o.flags|=DREFOBJ;
  749.         }else{
  750.             if(p->left->o.flags&VARADR){
  751.                 free(new);
  752.                 p->o=p->left->o;
  753.                 p->o.flags&=~VARADR;
  754.             }else{
  755.                 if(p->left->o.flags&SCRATCH){
  756.                     new->z=p->left->o;
  757.                     new->z.flags&=~DREFOBJ;
  758.                 }else{
  759.                 /* das hier funktioniert vermutlich auch nicht  */
  760.                     get_scratch(&new->z,p->left->ntyp->flags,p->ntyp->flags,p->left->ntyp);
  761.                 }
  762.                 new->code=ASSIGN;new->typf=POINTER;
  763.                 new->q1=p->left->o;
  764.                 new->q2.val.vlong=sizetab[POINTER];
  765.                 new->q2.flags=0;
  766.                 p->o=new->z;
  767.                 add_IC(new);
  768.                 p->o.flags|=DREFOBJ;
  769.             }
  770.         }
  771. /*            p->left->o.flags-=DREFOBJ|VARADR; Was sollte das??    */
  772.  
  773.         if(optflags&2){
  774.             while(rl){
  775.                 struct regargs_list *m;
  776.                 new=mymalloc(ICS);
  777.                 new->code=NOP;
  778.                 new->q1.flags=VAR;
  779.                 new->q1.v=rl->v;
  780.                 new->q1.val.vlong=l2zl(0L);
  781.                 new->typf=0;
  782.                 new->q2.flags=new->z.flags=0;
  783.                 add_IC(new);
  784.                 m=rl->next;free(rl);rl=m;
  785.             }
  786.         }
  787. #ifndef HAVE_REGPARMS
  788.         /*  gegebenenfalls Adresse des Ziels auf den Stack  */
  789.         if(!freturn(p->ntyp)){
  790. #ifdef ORDERED_PUSH
  791.             ierror(0);
  792. #endif
  793.             new=mymalloc(ICS);
  794.             new->code=ADDRESS;
  795.             new->typf=p->ntyp->flags&NU;
  796.             new->q1.flags=VAR;
  797.             new->q1.v=add_var(empty,clone_typ(p->ntyp),AUTO,0);
  798.             new->q1.val.vlong=l2zl(0L);
  799.             op=&new->q1;
  800.             new->q2.flags=0;
  801.             get_scratch(&new->z,POINTER,p->ntyp->flags&NU,0);
  802.             ret_obj=new->z;
  803.             add_IC(new);
  804.             new=mymalloc(ICS);
  805.             new->code=PUSH;
  806.             new->typf=POINTER;
  807.             new->q1=ret_obj;
  808.             new->q2.flags=new->z.flags=0;
  809.             new->q2.val.vlong=sizetab[POINTER];
  810.             add_IC(new);
  811.             sz=zladd(sz,sizetab[POINTER]);
  812.         }
  813. #endif
  814.         /*  Scratchregister evtl. sichern   */
  815.         savescratch(MOVEFROMREG,last_ic,0);
  816.         function_calls+=currentpri;
  817.         new=mymalloc(ICS);
  818.         new->code=CALL;
  819.         new->typf=FUNKT;
  820.         new->q1=p->o;
  821.         new->q2.flags=new->z.flags=0;
  822.         new->q2.val.vlong=sz; /*  Groesse der Parameter auf dem Stack */
  823.         add_IC(new);
  824.         r=0;
  825.         if((p->ntyp->flags&NQ)!=VOID){
  826.             new=mymalloc(ICS);
  827.             new->code=GETRETURN;
  828.             new->q1.flags=new->q2.flags=0;
  829.             new->q1.reg=freturn(p->ntyp);
  830.             new->q2.val.vlong=szof(p->ntyp);
  831.             new->typf=p->ntyp->flags;
  832.             if(freturn(p->ntyp)){
  833.               int t=p->ntyp->flags&NQ;
  834.               if(t==STRUCT||t==UNION){
  835.                 new->z.v=add_var(empty,clone_typ(p->ntyp),AUTO,0);
  836.                 new->z.flags=VAR;
  837.                 new->z.val.vlong=l2zl(0L);
  838.               }else{
  839.                 if(optflags&2){
  840.                   get_scratch(&new->z,p->ntyp->flags&NU,0,p->ntyp);
  841.                 }else{
  842.                   /* Suche geeignetes Register, um Rueckgabewert zu speichern. */
  843.                   struct regargs_list *l2;
  844.                   int r;
  845.                   r=new->q1.reg;
  846.                   if(regs[r]||!regok(r,p->ntyp->flags&NU,0)){
  847.                     r=0;
  848.                   }else{
  849.                     for(l2=rl;l2;l2=l2->next){
  850.                       if(l2->v&&abs(l2->reg)==r) {r=0;break;}
  851.                     }
  852.                   }
  853.                   if(r==0){
  854.                     for(r=1;r<=MAXR;r++){
  855.                       if(!regs[r]&®ok(r,p->ntyp->flags&NU,0)){
  856.                         for(l2=rl;l2;l2=l2->next){
  857.                           if(l2->v&&abs(l2->reg)==r) break;
  858.                         }
  859.                         if(l2) continue;
  860.                         break;
  861.                       }
  862.                     }
  863.                   }
  864.                   if(r>=1&&r<=MAXR){
  865.                     alloc_hardreg(r);
  866.                     new->z.flags=(REG|SCRATCH);
  867.                     new->z.reg=r;
  868.                   }else{
  869.                     get_scratch(&new->z,p->ntyp->flags&NU,0,p->ntyp);
  870.                   }
  871.                 }
  872.               }
  873.             } else
  874.               new->z=*op;
  875.             if((new->z.flags&(REG|DREFOBJ))==REG) r=new->z.reg;
  876.             p->o=new->z;
  877.             add_IC(new);
  878.         }else{
  879.             p->o.flags=0;
  880.         }
  881.         /*  Scratchregister evtl. wiederherstellen  */
  882.         savescratch(MOVETOREG,last_ic,r);
  883.         if(!(optflags&2)){
  884.           int r;
  885.           for(r=1;r<=MAXR;r++){
  886.             if(regs[r])
  887.               regs[r]|=(mregs[r]&32);
  888.           }
  889.         }
  890.         /*  Evtl. gespeicherte Registerargumente wiederherstellen.  */
  891.         while(rl){
  892.             struct regargs_list *m;
  893.             if(rl->v){
  894.                 new=mymalloc(ICS);
  895.                 new->code=MOVETOREG;
  896.                 new->typf=0;
  897.                 new->q1.flags=VAR|DONTREGISTERIZE;
  898.                 new->q1.v=rl->v;
  899.                 new->q1.val.vlong=l2zl(0L);
  900.                 new->z.flags=REG;
  901.                 new->z.reg=abs(rl->reg);
  902.                 new->q2.flags=0;
  903.                 new->q2.val.vlong=regsize[abs(rl->reg)];
  904.                 add_IC(new);
  905.             }else{
  906.                 new=mymalloc(ICS);
  907.                 new->code=FREEREG;
  908.                 new->typf=0;
  909.                 new->q1.flags=REG;
  910.                 new->q2.flags=new->z.flags=0;
  911.                 new->q1.reg=abs(rl->reg);
  912.                 add_IC(new);
  913.                 regs[abs(rl->reg)]=0;
  914.             }
  915.             m=rl->next;free(rl);rl=m;
  916.         }
  917. #ifdef ORDERED_PUSH
  918.         /* If arguments have been pushed nested we have to copy them and */
  919.         /* push them later. */
  920.         if(merk_fp&&first_pushed){
  921.           struct IC *p,*m=0,*np;
  922.           if(!lp) ierror(0);
  923.           for(p=merk_fp;p;){
  924.             np=p->next;
  925.             if(p->code==PUSH){
  926.               new=mymalloc(ICS);
  927.               *new=*p;
  928.               if(p->q1.flags){
  929.                 p->code=ASSIGN;
  930.                 p->z.flags=VAR;
  931.                 p->z.val.vlong=l2zl(0L);
  932.                 if(p->q1.flags&VAR){
  933.                   p->z.v=add_tmp_var(clone_typ(p->q1.v->vtyp));
  934.                 }else{
  935.                   struct Typ ts={0};
  936.                   ts.flags=p->typf;
  937.                   p->z.v=add_tmp_var(clone_typ(&ts));
  938.                 }
  939.                 new->q1=p->z;
  940.               }else{
  941.                 remove_IC(p);
  942.               }
  943.               add_IC(new);
  944.               if(!m) m=new;
  945.             }
  946.             if(p==lp) break;
  947.             p=np;
  948.           }
  949.           if(!m) ierror(0);
  950.           first_pushed=m;
  951.         }else
  952.           first_pushed=merk_fp;
  953. #endif
  954.         return;
  955.     }
  956.     if(p->flags>=PREINC&&p->flags<=POSTDEC){
  957.         struct obj o;
  958.         gen_IC(p->left,0,0);
  959.         if(p->flags==POSTINC||p->flags==POSTDEC){
  960.             new=mymalloc(ICS);
  961.             new->code=ASSIGN;
  962.             new->typf=p->ntyp->flags&NU;
  963.             new->q2.val.vlong=sizetab[p->ntyp->flags&NQ];
  964.             new->q1=p->left->o;
  965.             new->q1.flags&=~SCRATCH;
  966.             get_scratch(&new->z,p->left->ntyp->flags&NU,0,p->left->ntyp);
  967.             new->q2.flags=0;
  968.             o=new->z;
  969.             add_IC(new);
  970.             new=mymalloc(ICS);
  971.         }else o=p->left->o;
  972.         if((p->left->ntyp->flags&NQ)==POINTER){
  973.             if(p->flags==PREINC||p->flags==POSTINC) new->code=ADDI2P; else new->code=SUBIFP;
  974.             vlong=szof(p->left->ntyp->next);
  975.             new->q2.val.vint=zl2zi(vlong);
  976.             new->typf=INT;
  977.             new->q1=p->left->o;
  978.             new->z=p->left->o;
  979.             new->q2.flags=KONST;
  980.             add_IC(new);
  981.         }else{
  982.             if(p->flags==PREINC||p->flags==POSTINC) new->code=ADD; else new->code=SUB;
  983.             new->typf=p->ntyp->flags&NU;
  984.             new->q1=p->left->o;
  985.             new->z=p->left->o;
  986.             new->q2.flags=KONST;
  987.             vlong=l2zl(1L);vulong=zl2zul(vlong);vdouble=zl2zd(vlong);
  988.             if(new->typf==CHAR) new->q2.val.vchar=zl2zc(vlong);
  989.             if(new->typf==SHORT) new->q2.val.vshort=zl2zs(vlong);
  990.             if(new->typf==INT) new->q2.val.vint=zl2zi(vlong);
  991.             if(new->typf==LONG) new->q2.val.vlong=vlong;
  992.             if(new->typf==(UNSIGNED|CHAR)) new->q2.val.vuchar=zul2zuc(vulong);
  993.             if(new->typf==(UNSIGNED|SHORT)) new->q2.val.vushort=zul2zus(vulong);
  994.             if(new->typf==(UNSIGNED|INT)) new->q2.val.vuint=zul2zui(vulong);
  995.             if(new->typf==(UNSIGNED|LONG)) new->q2.val.vulong=vulong;
  996.             if(new->typf==DOUBLE) new->q2.val.vdouble=vdouble;
  997.             if(new->typf==FLOAT) new->q2.val.vfloat=zd2zf(vdouble);
  998.             add_IC(new);
  999.         }
  1000.         if(p->flags==POSTINC||p->flags==POSTDEC){
  1001.             if(p->left->o.flags&SCRATCH) free_reg(p->left->o.reg);
  1002.         }
  1003.         p->o=o;
  1004.         return;
  1005.     }
  1006.     if(p->flags==COND){
  1007.         int ltrue,lfalse,lout;
  1008.         ltrue=++label;lfalse=++label;lout=++label;
  1009.         gen_IC(p->left,ltrue,lfalse);
  1010.         if(!p->left->o.flags){
  1011.             free(new);
  1012.         }else{
  1013.             if(p->left->flags!=CEXPR){
  1014.                 gen_test(&p->left->o,p->left->ntyp->flags,BEQ,lfalse);
  1015.             }else{
  1016.                 eval_constn(p->left);
  1017.                 if(zleqto(vlong,l2zl(0L))&&zuleqto(vulong,ul2zul(0UL))&&zdeqto(vdouble,d2zd(0.0))){
  1018.                     gen_IC(p->right->right,0,0);
  1019.                     p->o=p->right->right->o;
  1020.                 }else{
  1021.                     gen_IC(p->right->left,0,0);
  1022.                     p->o=p->right->left->o;
  1023.                 }
  1024.                 return;
  1025.             }
  1026.         }
  1027.         gen_label(ltrue);
  1028.         gen_IC(p->right->left,0,0);
  1029.         if((p->ntyp->flags&NQ)!=VOID){
  1030.             convert(p->right->left,p->ntyp->flags&NU);
  1031.             if((p->right->left->o.flags&(SCRATCH|DREFOBJ))==SCRATCH){
  1032.                 p->o=p->right->left->o;
  1033.             }else{
  1034.                 get_scratch(&p->o,p->ntyp->flags&NU,0,p->ntyp);
  1035.                 new=mymalloc(ICS);
  1036.                 new->code=ASSIGN;
  1037.                 new->q1=p->right->left->o;
  1038.                 new->z=p->o;
  1039.                 new->q2.flags=0;
  1040.                 new->q2.val.vlong=szof(p->ntyp);
  1041.                 new->typf=p->ntyp->flags&NU;
  1042.                 p->o=new->z;
  1043.                 add_IC(new);
  1044.             }
  1045.         }else p->o.flags=0;
  1046.         new=mymalloc(ICS);
  1047.         new->code=BRA;
  1048.         new->typf=lout;
  1049.         add_IC(new);
  1050.         gen_label(lfalse);
  1051.         gen_IC(p->right->right,0,0);
  1052.         if((p->ntyp->flags&NQ)!=VOID){
  1053.             convert(p->right->right,p->ntyp->flags&NU);
  1054.             new=mymalloc(ICS);
  1055.             new->code=ASSIGN;
  1056.             new->q1=p->right->right->o;
  1057.             new->z=p->o;
  1058.             new->q2.flags=0;
  1059.             new->q2.val.vlong=szof(p->ntyp);
  1060.             new->typf=p->ntyp->flags&NU;
  1061.             add_IC(new);
  1062.         }
  1063.         gen_label(lout);
  1064.         return;
  1065.     }
  1066.     printf("Operation: %d=%s\n",p->flags,ename[p->flags]);
  1067.     ierror(0);
  1068.     free(new);
  1069.     p->o.flags=0;
  1070. }
  1071. #ifdef HAVE_REGPARMS
  1072. zlong push_args(struct argument_list *al,struct struct_declaration *sd,int n,struct regargs_list **rl,struct reg_handle *reg_handle,struct obj *radr,int rreg)
  1073. #else
  1074. zlong push_args(struct argument_list *al,struct struct_declaration *sd,int n,struct regargs_list **rl)
  1075. #endif
  1076. /*  Legt die Argumente eines Funktionsaufrufs in umgekehrter Reihenfolge    */
  1077. /*  auf den Stack. Es wird Integer-Erweiterung vorgenommen und float wird   */
  1078. /*  nach double konvertiert, falls kein Prototype da ist.                   */
  1079. {
  1080.     int t,reg,regpush,evaluated=0;
  1081.     struct IC *new;struct regargs_list *nrl;zlong sz,of;struct obj *arg;
  1082. #ifdef HAVE_REGPARMS
  1083.     int stdreg;
  1084.     if(!al&&!radr) return(0);
  1085.     if(radr){
  1086.       stdreg=rreg;
  1087.     }else{
  1088.       if(n<sd->count){
  1089.         stdreg=reg_parm(reg_handle,(*sd->sl)[n].styp,0);
  1090.       }else{
  1091.         if(sd->count)
  1092.           stdreg=reg_parm(reg_handle,al->arg->ntyp,1);
  1093.         else
  1094.           stdreg=reg_parm(reg_handle,al->arg->ntyp,0);
  1095.       }
  1096.     }
  1097.     reg=stdreg;
  1098. #else
  1099.     if(!al) return(0);
  1100.     reg=0;
  1101. #endif
  1102. #ifdef HAVE_REGPARMS
  1103.     if(!radr){
  1104. #endif
  1105.       if(!al->arg) ierror(0);
  1106.       if(!sd) ierror(0);
  1107.       if(n<sd->count){
  1108.         t=(*sd->sl)[n].styp->flags;sz=szof((*sd->sl)[n].styp);
  1109.         reg=(*sd->sl)[n].reg;
  1110.       }else{
  1111.         t=al->arg->ntyp->flags;sz=szof(al->arg->ntyp);
  1112.       }
  1113.       if((t&NQ)>=CHAR&&(t&NQ)<=LONG) {t=int_erw(t);sz=sizetab[t&NQ];}
  1114.       if((t&NQ)==FLOAT&&n>=sd->count) {t=DOUBLE;sz=sizetab[t];}
  1115. #ifdef HAVE_REGPARMS
  1116.     }else{
  1117.       t=POINTER;sz=sizetab[POINTER];
  1118.     }
  1119. #endif
  1120.     if(reg<0) {reg=-reg;regpush=1;} else regpush=0;
  1121.     sz=zlmult(zldiv(zladd(sz,zlsub(maxalign,l2zl(1L))),maxalign),maxalign);
  1122. #ifdef ORDERED_PUSH
  1123.     if(reg==0||regpush){
  1124.       new=mymalloc(ICS);
  1125.       if(!radr&&!evaluated){
  1126.         gen_IC(al->arg,0,0);
  1127.         convert(al->arg,t&NU);
  1128.         evaluated=1;
  1129.         new->q1=al->arg->o;
  1130.       }else
  1131.         new->q1=*radr;
  1132.       /*  Parameteruebergabe ueber Stack. */
  1133.       new->code=PUSH;
  1134.       new->typf=t;
  1135.       new->q2.flags=new->z.flags=0;
  1136.       new->q2.val.vlong=sz;
  1137.       if(regpush){
  1138.         if(c_flags[26]&USEDFLAG){
  1139.           new->q1.am=new->q2.am=new->z.am=0;
  1140.           new->line=line; new->file=0;
  1141.           insert_IC(last_ic,new);
  1142.         }else{
  1143.           new->q1.flags=0;
  1144.           add_IC(new);
  1145.         }
  1146.       }else{
  1147.         add_IC(new);
  1148.       }
  1149.       if(!first_pushed) first_pushed=new;
  1150.       if(!al->next&&!regpush) return sz;
  1151.     }
  1152. #endif
  1153. #ifdef HAVE_REGPARMS
  1154.     if(radr){
  1155.       if(al) of=push_args(al,sd,0,rl,reg_handle,0,0); else of=l2zl(0L);
  1156.     }else{
  1157.       if(al->next) of=push_args(al->next,sd,n+1,rl,reg_handle,0,0); else of=l2zl(0L);
  1158.     }
  1159. #else
  1160.     if(al->next) of=push_args(al->next,sd,n+1,rl); else of=l2zl(0L);
  1161. #endif
  1162. #ifdef ORDERED_PUSH
  1163.     if(reg==0) return zladd(of,sz);
  1164. #endif
  1165.  
  1166.     if(regpush) of=zladd(of,sz);
  1167.  
  1168. #ifdef HAVE_REGPARMS
  1169.     if(radr){
  1170.       arg=radr;
  1171.     }else{
  1172.       if(!evaluated){
  1173.         gen_IC(al->arg,0,0);
  1174.         convert(al->arg,t&NU);
  1175.         evaluated=1;
  1176.       }
  1177.       arg=&al->arg->o;
  1178.     }
  1179. #else
  1180.     if(!evaluated){
  1181.       gen_IC(al->arg,0,0);
  1182.       convert(al->arg,t&NU);
  1183.       evaluated=1;
  1184.     }
  1185.     arg=&al->arg->o;
  1186. #endif
  1187. #ifndef ORDERED_PUSH
  1188.     if(reg==0||regpush){
  1189.         /*  Parameteruebergabe ueber Stack. */
  1190.         new=mymalloc(ICS);
  1191.         new->code=PUSH;
  1192.         new->typf=t;
  1193.         new->q1=*arg;
  1194.         if(regpush&&!(c_flags[26]&USEDFLAG)) new->q1.flags=0;
  1195.         new->q2.flags=new->z.flags=0;
  1196.         new->q2.val.vlong=sz;
  1197.         add_IC(new);
  1198.         if(!regpush) return(zladd(of,sz));
  1199.     }
  1200. #endif
  1201.     if(reg){
  1202.         /*  Parameteruebergabe in Register. */
  1203.         struct Var *v=0; struct Typ *t2;
  1204.         if(optflags&2){
  1205.         /*  Version fuer Optimizer. */
  1206.             t2=mymalloc(TYPS);
  1207.             t2->flags=t;
  1208.             if((t&NQ)==POINTER){
  1209.                 t2->next=mymalloc(TYPS);
  1210.                 t2->next->flags=VOID;
  1211.                 t2->next->next=0;
  1212.             }else t2->next=0;
  1213.             v=add_var(empty,t2,AUTO,0);
  1214.             new=mymalloc(ICS);
  1215.             new->code=ASSIGN;
  1216.             new->typf=t;
  1217.             new->q1=*arg;
  1218.             new->q2.flags=0;
  1219.             new->q2.val.vlong=sizetab[t&NQ];
  1220.             new->z.flags=VAR;
  1221.             new->z.v=v;
  1222.             new->z.val.vlong=l2zl(0L);
  1223.             add_IC(new);
  1224.             nrl=mymalloc(sizeof(*nrl));
  1225.             nrl->next=*rl;
  1226.             nrl->reg=reg;
  1227.             nrl->v=v;
  1228.             *rl=nrl;
  1229. #ifdef HAVE_REGPARMS
  1230.             if(radr||(!radr&&rreg==-1))
  1231. #else
  1232.             if(n==0)
  1233. #endif
  1234.             {
  1235.             /*  Letztes Argument; jetzt in Register laden.  */
  1236.                 for(;nrl;nrl=nrl->next){
  1237.                     new=mymalloc(ICS);
  1238.                     new->code=ASSIGN;
  1239.                     new->typf=nrl->v->vtyp->flags|VOLATILE;
  1240.                     new->q1.flags=VAR;
  1241.                     new->q1.v=nrl->v;
  1242.                     new->q1.val.vlong=l2zl(0L);
  1243.                     new->q2.flags=0;
  1244.                     new->q2.val.vlong=szof(nrl->v->vtyp);
  1245.                     new->z.flags=VAR;
  1246.                     new->z.val.vlong=l2zl(0L);
  1247.                     new->z.v=add_var(empty,clone_typ(nrl->v->vtyp),AUTO,0);
  1248.                     new->z.v->reg=nrl->reg;
  1249.                     nrl->v=new->z.v;
  1250.                     add_IC(new);
  1251.                 }
  1252.             }
  1253.             return(of);
  1254.         }else{
  1255.         /*  Nicht-optimierende Version. */
  1256.             if(!regs[reg]){
  1257.                 new=mymalloc(ICS);
  1258.                 new->code=ALLOCREG;
  1259.                 new->typf=0;
  1260.                 new->q1.flags=REG;
  1261.                 new->q1.reg=reg;
  1262.                 new->q2.flags=new->z.flags=0;
  1263.                 add_IC(new);
  1264.                 regs[reg]=33;regused[reg]++;
  1265.             }else{
  1266.                 if(arg->flags!=(REG|SCRATCH)||arg->reg!=reg){
  1267.                     t2=clone_typ(regtype[reg]);
  1268.                     v=add_var(empty,t2,AUTO,0);
  1269.                     v->flags|=USEDASADR;
  1270.                     new=mymalloc(ICS);
  1271.                     new->code=MOVEFROMREG;
  1272.                     new->typf=0;
  1273.                     new->q1.flags=REG;
  1274.                     new->q1.reg=reg;
  1275.                     new->q2.flags=0;
  1276.                     new->q2.val.vlong=regsize[reg];
  1277.                     new->z.flags=VAR|DONTREGISTERIZE;
  1278.                     new->z.v=v;
  1279.                     new->z.val.vlong=l2zl(0L);
  1280.                     add_IC(new);
  1281.                 }else regs[reg]|=32;
  1282.             }
  1283.             new=mymalloc(ICS);
  1284.             new->code=ASSIGN;
  1285.             new->typf=t;
  1286.             new->q1=*arg;
  1287.             /* Testen, ob Quellregister gesichert wurde. Unschoen. */
  1288.             if((new->q1.flags®)){
  1289.               struct regargs_list *p;
  1290.               for(p=*rl;p;p=p->next){
  1291.                 if(p->v&&abs(p->reg)==new->q1.reg) {new->q1.v=p->v;break;}
  1292.               }
  1293.               if(p&&new->q1.v){
  1294.                 new->q1.flags&=~REG;
  1295.                 new->q1.flags|=VAR;
  1296.                 new->q1.val.vlong=l2zl(0L);
  1297.               }
  1298.             }
  1299.             new->q2.flags=new->z.flags=0;
  1300.             new->q2.val.vlong=sizetab[t&NQ];
  1301.             new->z.flags=REG;
  1302.             new->z.reg=reg;
  1303.             add_IC(new);
  1304.             nrl=mymalloc(sizeof(*nrl));
  1305.             nrl->next=*rl;
  1306.             nrl->reg=reg;
  1307.             nrl->v=v;
  1308.             *rl=nrl;
  1309.             return(of);
  1310.         }
  1311.     }
  1312. }
  1313.  
  1314. void convert(np p,int f)
  1315. /*  konvertiert das Objekt in p->o in bestimmten Typ    */
  1316. {
  1317.     struct IC *new;
  1318.     if((f&NQ)==VOID||(p->ntyp->flags&NU)==f) return;
  1319.     if(p->flags==CEXPR||p->flags==PCEXPR){
  1320.         eval_constn(p);
  1321.         p->ntyp->flags=f;
  1322.         insert_const(p);
  1323.         p->o.val=p->val;
  1324.         return;
  1325.     }
  1326.     if(!must_convert(p,f)) return;
  1327.     new=mymalloc(ICS);
  1328.     new->q1=p->o;
  1329.     new->q2.flags=0;
  1330.     new->code=CONVCHAR+(p->ntyp->flags&NQ)-CHAR;
  1331.     if(p->ntyp->flags&UNSIGNED) new->code+=8;
  1332.     new->typf=f;
  1333.     if(!regok(p->o.reg,f,0)||!(p->o.flags&SCRATCH)){
  1334.         get_scratch(&new->z,f,0,0);
  1335.         p->o=new->z;
  1336.         add_IC(new);
  1337.     }else{
  1338.         new->z=p->o;new->z.flags&=~DREFOBJ;
  1339.         p->o=new->z;
  1340.         add_IC(new);
  1341.     }
  1342. }
  1343.  
  1344. void alloc_hardreg(int r)
  1345. /*  Belegt Register r.  */
  1346. {
  1347.   struct IC *new;
  1348.   if(nocode) return;
  1349.   if(DEBUG&16) printf("allocated %s\n",regnames[r]);
  1350.   regs[r]=1;regused[r]++;
  1351.   new=mymalloc(ICS);
  1352.   new->code=ALLOCREG;
  1353.   new->typf=0;
  1354.   new->q1.flags=REG;
  1355.   new->q1.reg=r;
  1356.   new->q2.flags=new->z.flags=0;
  1357.   add_IC(new);
  1358. }
  1359.  
  1360. int allocreg(int f,int mode)
  1361. /*  Fordert Register fuer Typ f an.                     */
  1362. {
  1363.   int i;
  1364.   if(nocode) return(1);
  1365.   for(i=1;i<=MAXR;i++){
  1366.     if(!regs[i]&®ok(i,f,mode)){
  1367.       alloc_hardreg(i);
  1368.       return(i);
  1369.     }
  1370.   }
  1371.   if(DEBUG&1) printf(">%sCouldn't allocate register for type %d\n",string,f);
  1372.   return(0);
  1373. }
  1374. void free_reg(int r)
  1375. /*  Gibt Register r frei                                */
  1376. /*  Eintrag eines IC fehlt noch                         */
  1377. {
  1378.     struct IC *new;
  1379.     if(!r||nocode) return;
  1380.     if(regs[r]==0) {printf("Register %d(%s):\n",r,regnames[r]);ierror(0);}
  1381.     if(DEBUG&16) printf("freed %s\n",regnames[r]);
  1382.     new=mymalloc(ICS);
  1383.     new->code=FREEREG;
  1384.     new->typf=0;
  1385.     new->q1.flags=REG;
  1386.     new->q1.reg=r;
  1387.     new->q2.flags=new->z.flags=0;
  1388.     add_IC(new);
  1389.     regs[r]=0;
  1390. }
  1391. void gen_label(int l)
  1392. /*  Erzeugt ein Label                                   */
  1393. {
  1394.     struct IC *new;
  1395.     new=mymalloc(ICS);
  1396.     new->code=LABEL;
  1397.     new->typf=l;
  1398.     new->q1.flags=new->q2.flags=new->z.flags=0;
  1399.     add_IC(new);
  1400. }
  1401. void gen_cond(struct obj *p,int m,int l1,int l2)
  1402. /*  Generiert code, der 0 oder 1 in Register schreibt. Schreibt obj nach p. */
  1403. {
  1404.     struct IC *new;
  1405.     struct obj omerk;
  1406.     new=mymalloc(ICS);
  1407.     new->code=ASSIGN;
  1408.     new->typf=INT;
  1409.     new->q1.flags=KONST;
  1410.     new->q2.flags=0;
  1411.     new->q2.val.vlong=sizetab[INT];
  1412.     if(!m) vlong=l2zl(1L); else vlong=l2zl(0L);
  1413.     new->q1.val.vint=zl2zi(vlong);
  1414.     get_scratch(&new->z,INT,0,0);
  1415.     omerk=new->z;
  1416.     add_IC(new);
  1417.     new=mymalloc(ICS);
  1418.     new->code=BRA;
  1419.     new->typf=l2;
  1420.     add_IC(new);
  1421.     gen_label(l1);
  1422.     new=mymalloc(ICS);
  1423.     new->code=ASSIGN;
  1424.     new->typf=INT;
  1425.     new->q1.flags=KONST;
  1426.     new->q2.flags=0;
  1427.     new->q2.val.vlong=sizetab[INT];
  1428.     if(!m) vlong=l2zl(0L); else vlong=l2zl(1L);
  1429.     new->q1.val.vint=zl2zi(vlong);
  1430.     new->z=omerk;
  1431. /*    new->z.reg=r;
  1432.     new->z.flags=SCRATCH|REG;*/
  1433.     add_IC(new);
  1434.     gen_label(l2);
  1435.     *p=omerk;
  1436. }
  1437. void scratch_var(struct obj *o,int t,struct Typ *typ)
  1438. /*  liefert eine temporaere Variable                            */
  1439. /*  nicht effizient, aber wer hat schon so wenig Register...    */
  1440. {
  1441.   struct Typ *nt;
  1442.   if((t&NQ)<CHAR||(t&NQ)>POINTER){
  1443.     if(!typ) ierror(0);
  1444.     nt=clone_typ(typ);
  1445.   }else{
  1446.     nt=mymalloc(TYPS);
  1447.     nt->flags=t&NU;
  1448.     if((t&NQ)==POINTER){
  1449.       nt->next=mymalloc(TYPS);
  1450.       nt->next->flags=VOID;
  1451.       nt->next->next=0;
  1452.     }else nt->next=0;
  1453.   }
  1454.   o->flags=SCRATCH|VAR;o->reg=0;
  1455.   o->v=add_var(empty,nt,AUTO,0);
  1456.   o->val.vlong=l2zl(0L);
  1457. }
  1458. void get_scratch(struct obj *o,int t1,int t2,struct Typ *typ)
  1459. /*  liefert ein Scratchregister oder eine Scratchvariable       */
  1460. {
  1461.     if(!(optflags&2)&&(o->reg=allocreg(t1,t2))){
  1462.         o->flags=SCRATCH|REG;
  1463.     }else{
  1464.         scratch_var(o,t1,typ);
  1465.     }
  1466. }
  1467. int do_arith(np p,struct IC *new,np dest,struct obj *o)
  1468. /*  erzeugt IC new fuer einen arithmetischen Knoten und speichert das   */
  1469. /*  Resultat vom Unterknoten dest in o (fuer a op= b)               */
  1470. /*  liefert 0, wenn dest nicht gefunden                             */
  1471. {
  1472.     int f=0,mflags;
  1473.     new->code=p->flags;
  1474.     if(new->code==PMULT) new->code=MULT;
  1475.     gen_IC(p->left,0,0);
  1476.     if(dest&&p->left==dest) {*o=p->left->o;f++;}
  1477.     gen_IC(p->right,0,0);
  1478.     if(dest&&p->right==dest) {*o=p->right->o;f++;}
  1479.     if(dest){ mflags=dest->o.flags;dest->o.flags&=(~SCRATCH);}
  1480.  
  1481.     if((p->left->ntyp->flags&NQ)==POINTER&&(p->right->ntyp->flags&NQ)==POINTER){
  1482.     /*  Subtrahieren zweier Pointer                                 */
  1483.         if(p->flags!=SUB) ierror(0);
  1484.         new->typf=PTRDIFF_T;
  1485.         new->code=SUBPFP;
  1486.         new->q1=p->left->o;
  1487.         new->q2=p->right->o;
  1488.         if(!dest&&(p->left->o.flags&SCRATCH)&®ok(p->left->o.reg,INT,0)){
  1489.             new->z=p->left->o;
  1490.             new->z.flags&=~DREFOBJ;
  1491.         }else{
  1492.             if(USEQ2ASZ&&(p->right->o.flags&SCRATCH)&®ok(p->right->o.reg,INT,0)){
  1493.                 new->z=p->right->o;
  1494.                 new->z.flags&=(~DREFOBJ);
  1495.             }else{
  1496.                 get_scratch(&new->z,INT,0,0);
  1497.             }
  1498.         }
  1499.         p->o=new->z;
  1500.         add_IC(new);
  1501.         if(!zlleq(szof(p->left->ntyp->next),l2zl(1L))){
  1502.             new=mymalloc(ICS);
  1503.             new->code=DIV;
  1504.             new->q1=p->o;
  1505.             new->q2.flags=KONST;
  1506.             vlong=szof(p->left->ntyp->next);
  1507.             vint=zl2zi(vlong);
  1508.             new->q2.val.vint=vint;
  1509.             new->z=p->o;
  1510.             new->typf=INT;
  1511.             add_IC(new);
  1512.         }
  1513.         if(dest) dest->o.flags=mflags;
  1514.         return(f);
  1515.     }
  1516.     if((p->flags==ADD||p->flags==SUB)&&(p->ntyp->flags&NQ)==POINTER){
  1517.     /*  Addieren und Subtrahieren eines Integers zu einem Pointer   */
  1518.         if(p->flags==ADD) new->code=ADDI2P; else new->code=SUBIFP;
  1519.         new->typf=p->right->ntyp->flags&NU;
  1520.         new->q1=p->left->o;
  1521.         /*  kleinere Typen als MINADDI2P erst in diesen wandeln */
  1522.         if((new->typf&NQ)<MINADDI2P){convert(p->right,/*UNSIGNED|*/MINADDI2P);new->typf=/*UNSIGNED|*/MINADDI2P;}
  1523.         new->q2=p->right->o;
  1524.         if(!dest&&(p->left->o.flags&SCRATCH)&®ok(new->q1.reg,POINTER,p->left->ntyp->next->flags&NU)){
  1525.             new->z=p->left->o;
  1526.             new->z.flags&=(~DREFOBJ);
  1527.         }else{
  1528.             get_scratch(&new->z,POINTER,p->left->ntyp->next->flags&NU,0);
  1529.         }
  1530.         p->o=new->z;
  1531.         add_IC(new);
  1532.         if(dest) dest->o.flags=mflags;
  1533.         return(f);
  1534.     }
  1535.     convert(p->left,p->ntyp->flags&NU);
  1536.     convert(p->right,p->ntyp->flags&NU);
  1537.     new->q1=p->left->o;
  1538.     new->q2=p->right->o;
  1539.     new->typf=p->ntyp->flags&NU;
  1540.     /*  Bei dest!=0, d.h. ASSIGNADD, darf q1 nicht als Ziel benuzt werden!  */
  1541.     if(!dest&&(new->q1.flags&SCRATCH)&®ok(new->q1.reg,p->ntyp->flags,0)){
  1542.         new->z=new->q1;
  1543.         new->z.flags&=~DREFOBJ;
  1544.     }else{
  1545.         if((new->q2.flags&SCRATCH)&®ok(new->q2.reg,p->ntyp->flags,0)){
  1546.             if((p->flags>=OR&&p->flags<=AND)||p->flags==ADD||p->flags==MULT||p->flags==PMULT){
  1547.             /*  bei kommutativen Operatoren vertauschen     */
  1548.                 new->z=new->q2;
  1549.                 new->q2=new->q1;
  1550.                 new->q1=new->z;
  1551.                 new->z.flags&=~DREFOBJ;
  1552.             }else{
  1553.                 if(USEQ2ASZ){
  1554.                     new->z=new->q2;
  1555.                     new->z.flags&=~DREFOBJ;
  1556.                 }else{
  1557.                     get_scratch(&new->z,new->typf,0,0);
  1558.                 }
  1559.             }
  1560.         }else{
  1561.             get_scratch(&new->z,new->typf,0,0);
  1562.         }
  1563.     }
  1564.     p->o=new->z;
  1565.     add_IC(new);
  1566.     if(dest) dest->o.flags=mflags;
  1567.     return(f);
  1568. }
  1569. void savescratch(int code,struct IC *p,int dontsave)
  1570. /*  speichert Scratchregister bzw. stellt sie wieder her (je nach code  */
  1571. /*  entweder MOVEFROMREG oder MOVETOREG)                                */
  1572. {
  1573.     int i,s,e,b;struct IC *new;
  1574.     if(code==MOVETOREG){ s=1;e=MAXR+1;b=1;} else {s=MAXR;e=0;b=-1;}
  1575.     for(i=s;i!=e;i+=b){
  1576.         if(regs[i]&&!(regs[i]&32)&®scratch[i]&&i!=dontsave){
  1577.             if(!regsbuf[i]){
  1578.                 struct Typ *t;
  1579.                 if(code!=MOVEFROMREG) continue;
  1580.                 t=clone_typ(regtype[i]);
  1581.                 regsbuf[i]=add_var(empty,t,AUTO,0);
  1582.                 regsbuf[i]->flags|=USEDASADR;
  1583.                 regbnesting[i]=nesting;
  1584.             }
  1585.             new=mymalloc(ICS);
  1586.             new->typf=new->q2.flags=0;
  1587.             new->line=0;new->file=0;
  1588.             new->code=code;
  1589.             if(code==MOVEFROMREG){
  1590.                 new->q1.flags=REG;new->q1.reg=i;
  1591.                 new->z.flags=VAR|DONTREGISTERIZE;new->z.v=regsbuf[i];
  1592.                 new->z.val.vlong=l2zl(0L);
  1593.             }else{
  1594.                 new->z.flags=REG;new->z.reg=i;
  1595.                 new->q1.flags=VAR|DONTREGISTERIZE;new->q1.v=regsbuf[i];
  1596.                 new->q1.val.vlong=l2zl(0L);
  1597.             }
  1598.             new->use_cnt=new->change_cnt=0;
  1599.             new->use_list=new->change_list=0;
  1600.             insert_IC(p,new);
  1601.         }
  1602.     }
  1603. }
  1604.  
  1605.